package com.qyxx.platform.inf;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.qyxx.platform.inf.adapter.AdapterException;
import com.qyxx.platform.inf.adapter.AdapterProperties;
import com.qyxx.platform.inf.adapter.ClassLoaderUtil;
import com.qyxx.platform.inf.adapter.INeiAdapter;

/**
 *  接口适配器工厂
 *  
 *  @author gxj
 *  @version 1.0 2014-4-16 下午02:35:18
 *  @since jdk1.6
 */
public class NeiAdapterFactory {

	private Log logger = LogFactory.getLog(NeiAdapterFactory.class);
	
	/**
	 * 适配器工厂对象
	 */
	private static NeiAdapterFactory instance;
	
	/**
	 * 接口适配器缓存对象
	 */
	private ConcurrentMap<String, INeiAdapter> neiAdapterMap = new ConcurrentHashMap<String, INeiAdapter>();
	
	private NeiAdapterFactory() {}
	
	private Lock lock = new ReentrantLock();
	
	/**
	 * 获取适配器工厂的单例对象
	 * @return
	 */
	public synchronized static NeiAdapterFactory getInstance() {
		if(null==instance) {
			instance = new NeiAdapterFactory();
		}
		return instance;
	}
	
	/**
	 * 获取接口适配器对象
	 * 
	 * 能根据ap所带信息从neiAdapterMap找到对应的适配器对象，
	 * 若找到，则直接返回适配器对象实例；若找不到，
	 * 则根据ap所带信息创建一个适配器对象实例，加入到neiAdapterMap中，同时返回
	 * @param ap
	 * @return
	 */
	public INeiAdapter getNeiApater(AdapterProperties ap) throws AdapterException {
		if(null==ap.getAdapterCode()) {
			return null;
		}
		INeiAdapter nei = neiAdapterMap.get(ap.getAdapterCode());
		if(null==nei) {
			try {
				Class cls = Class.forName(ap.getAdapterClass());
				nei = (INeiAdapter)cls.newInstance();
				neiAdapterMap.put(ap.getAdapterCode(), nei);
				nei.init(ap);
			} catch (ClassNotFoundException e) {
				throw new AdapterException("接口" + ap.getAdapterName() + "的适配器类" + ap.getAdapterClass() + "找不到", e);
			} catch (InstantiationException e) {
				throw new AdapterException("接口" + ap.getAdapterName() + "的适配器类" + ap.getAdapterClass() + "实例化出错", e);
			} catch (IllegalAccessException e) {
				throw new AdapterException("接口" + ap.getAdapterName() + "的适配器类" + ap.getAdapterClass() + "实例化出错", e);
			} catch (AdapterException e) {
				throw new AdapterException("接口" + ap.getAdapterName() + "的适配器初始化失败", e);
			} catch(Exception e) {
				throw new AdapterException("接口" + ap.getAdapterName() + "的适配器初始化失败", e);
			}
		}
		return nei;
	}
	
	/**
	 * 销毁所有适配器
	 */
	public synchronized void destroy() {
		if(null!=neiAdapterMap && !neiAdapterMap.isEmpty()) {
			for(INeiAdapter nea : neiAdapterMap.values()) {
				try {
					if(null!=nea) {
						nea.destroy();
					}
					logger.info("接口" + (nea.getAdapterProperties()!=null?nea.getAdapterProperties().getAdapterName():"") + "已销毁");
				} catch (AdapterException e) {
					logger.error("销毁适配器实例出现异常", e);
				}
			}
			neiAdapterMap.clear();
			neiAdapterMap = null;
		}
	}
	
	/**
	 * 同步接口适配器对象，重启适配器实例功能
	 * 
	 * 能根据ap所带信息从neiAdapterMap找到对应的适配器对象，
	 * 若找到，则更新适配器对象实例；若找不到，
	 * 则根据ap所带信息创建一个适配器对象实例，加入到neiAdapterMap中，同时返回
	 * @param ap
	 * @return
	 */
	public INeiAdapter syncNeiApater(AdapterProperties ap) throws AdapterException {
		if(null==ap.getAdapterCode()) {
			return null;
		}
		INeiAdapter nei = null;
		lock.lock();
		try {
			nei = neiAdapterMap.get(ap.getAdapterCode());
			if(null==nei) {
				//不存在时，则生成一个实例
				try {
					Class cls = Class.forName(ap.getAdapterClass());
					nei = (INeiAdapter)cls.newInstance();
					neiAdapterMap.put(ap.getAdapterCode(), nei);
					nei.init(ap);
				} catch (ClassNotFoundException e) {
					throw new AdapterException("接口" + ap.getAdapterName() + "的适配器类" + ap.getAdapterClass() + "找不到", e);
				} catch (InstantiationException e) {
					throw new AdapterException("接口" + ap.getAdapterName() + "的适配器类" + ap.getAdapterClass() + "实例化出错", e);
				} catch (IllegalAccessException e) {
					throw new AdapterException("接口" + ap.getAdapterName() + "的适配器类" + ap.getAdapterClass() + "实例化出错", e);
				} catch (AdapterException e) {
					throw new AdapterException("接口" + ap.getAdapterName() + "的适配器初始化失败", e);
				} catch(Exception e) {
					throw new AdapterException("接口" + ap.getAdapterName() + "的适配器初始化失败", e);
				}
			} else {
				//存在时，先将原有的销毁，再生成一个新的实例，即重启功能
				try {
					nei.destroy();
				} catch(Exception e) {
					logger.error("接口" + (nei.getAdapterProperties()!=null?nei.getAdapterProperties().getAdapterName():"") + "销毁时出现异常", e);
				}
				neiAdapterMap.remove(ap.getAdapterCode());
				try {
					Class cls = Class.forName(ap.getAdapterClass());
					nei = (INeiAdapter)cls.newInstance();
					neiAdapterMap.put(ap.getAdapterCode(), nei);
					nei.init(ap);
				} catch (ClassNotFoundException e) {
					throw new AdapterException("接口" + ap.getAdapterName() + "的适配器类" + ap.getAdapterClass() + "找不到", e);
				} catch (InstantiationException e) {
					throw new AdapterException("接口" + ap.getAdapterName() + "的适配器类" + ap.getAdapterClass() + "实例化出错", e);
				} catch (IllegalAccessException e) {
					throw new AdapterException("接口" + ap.getAdapterName() + "的适配器类" + ap.getAdapterClass() + "实例化出错", e);
				} catch (AdapterException e) {
					throw new AdapterException("接口" + ap.getAdapterName() + "的适配器初始化失败", e);
				} catch(Exception e) {
					throw new AdapterException("接口" + ap.getAdapterName() + "的适配器初始化失败", e);
				}
			}
		} finally {
			lock.unlock();
		}
		return nei;
	}
	
	/**
	 * 更新适配器属性值，如：设置适配器状态
	 * 
	 * 主要用于适配器的挂起功能
	 * @param ap
	 * @return
	 */
	public boolean updateNeiApaterProperties(AdapterProperties ap) throws AdapterException {
		INeiAdapter nei = null;
		lock.lock();
		try {
			nei = neiAdapterMap.get(ap.getAdapterCode());
			if(null!=nei) {
				nei.setAdapterProperties(ap);
			} else {
				return false;
			}
		} finally {
			lock.unlock();
		}
		return true;
	}
	
	/**
	 * 加载jar包到ClassPath
	 * @param fileName jar包全路径，如：/jar/test.jar
	 */
	public synchronized void addJarToClassPath(String fileName) {
		try {
			ClassLoaderUtil.getInstance().addFile(fileName);
		} catch(Exception e) {
			logger.error("加载jar包" + fileName + "失败", e);
		}
	}
	
	/**
	 * 加载jar包到ClassPath
	 * @param fileName jar包全路径，如：/jar/test.jar
	 */
	public synchronized void addJarsToClassPath(List<String> fileNameList) {
		if(null!=fileNameList) {
			for(String fileName : fileNameList) {
				try {
					ClassLoaderUtil.getInstance().addFile(fileName);
				} catch(Exception e) {
					logger.error("加载jar包" + fileName + "失败", e);
				}
			}
		}
	}
	
	/**
	 * 返回适配器属性列表
	 * @return
	 */
	public List<AdapterProperties> getNeiAdapterPropertiesList() {
		List<AdapterProperties> neaList = new ArrayList<AdapterProperties>();
		if(null!=neiAdapterMap) {
			for(INeiAdapter nei : neiAdapterMap.values()) {
				neaList.add(nei.getAdapterProperties());
			}
		}
		return neaList;
	}
	
	/**
	 * 移除接口适配器对象
	 * 
	 * @param ap
	 */
	public void removeNeiApater(AdapterProperties ap) {
		if(null!=ap.getAdapterCode()) {
			INeiAdapter nei = neiAdapterMap.get(ap.getAdapterCode());
			if(null!=nei) {
				try {
					nei.destroy();
				} catch (AdapterException e) {
					logger.error("接口" + (nei.getAdapterProperties()!=null?nei.getAdapterProperties().getAdapterName():"") + "销毁时出现异常", e);
				}
			}
			neiAdapterMap.remove(ap.getAdapterCode());
			logger.info("移除接口" + ap.getAdapterName() + "成功");
		}
	}
	
}
